<template>
    <el-dialog v-if="dialogVisible" title="点读" :visible.sync="dialogVisible" width="1380px" :before-close="handleClose"
        :modal="false">
        <el-row class="container">
            <el-col :span="12" class="container__pointer">
                <div class="container__pointer-title">
                    <h1>{{ item.title }}</h1>
                    <el-button type="primary" size="mini" class="container__pointer-title-btn"
                        @click="changeBorderColor(this)">切换点读框颜色</el-button>
                </div>
                <div class="container__pointer-image">
                    <canvas ref="myCanvas" @mousedown="handleMouseDown" @mouseup="handleMouseUp"
                        @mousemove="handleMouseMove" @mouseout="handleMouseOut">
                        Your browser does not support the canvas element.
                    </canvas>
                    <img @load="setCanvasWidthHight" :src="item.url" />
                </div>
                <div class="pointer-music"></div>
            </el-col>
            <el-col :span="12" class="container__audio">
                <template v-if="item.pointList.length">
                    <div class="container__audio-row" v-for="(item, index) in item.pointList" :key="item.updateTime">
                        <div class="container__audio-row-top">
                            <h1>点读区域{{ index + 1 }}</h1>
                            <div>
                                <el-button size="mini" type="primary" @click="translatePointer(index)">翻译</el-button>
                                <el-button size="mini" type="warning" @click="repaint(index)">{{
                                    item.repaint ? '取消' : '重画'
                                    }}</el-button>
                                <el-button size="mini" type="danger" @click="delPointer(index)">删除</el-button>
                            </div>
                        </div>

                        <div class="container__audio-row-content">
                            <h2>对应音频<b>{{ audioList[0].title }}</b></h2>
                            <div class="container__audio-row-content-time">
                                <ul class="container__audio-row-content-time-ul">
                                    <li>
                                        <span>开始时间
                                            <input type="text" name="start-sec" v-model="item.startTime" />
                                        </span>
                                        <audio :currenttime="item.startTime" @play="handlePlay($event, item, 'start')"
                                            @timeupdate="handleTime($event, index, 'start')" :src="audioList[0].url"
                                            controls="controls"></audio>
                                    </li>
                                    <li>
                                        <span>结束时间
                                            <input type="text" name="end-sec" v-model="item.endTime" />
                                        </span>
                                        <audio :currenttime="item.endTime" @play="handlePlay($event, item, 'end')"
                                            @timeupdate="handleTime($event, index, 'end')" :src="audioList[0].url"
                                            controls="controls"></audio>
                                    </li>
                                </ul>
                                <el-button @click="tryListen(index)" size="mini" type="primary">{{ item.isPlaying ? '取消'
                                    : '试听' }}</el-button>
                            </div>
                            <ul class="container__audio-row-content-text">
                                <li class="container__audio-row-content-text-row">
                                    <div class="span">
                                        <span><b style="color: red">*</b>原文</span>
                                    </div>
                                    <div class="text">
                                        <textarea style="" name="origin-text" v-model="item.text" rows="3"
                                            placeholder="必填，为保证点读效果，请填写音频对应的文字，暂时只支持英文和英文标点符号。"></textarea>
                                    </div>
                                </li>
                                <li class="container__audio-row-content-text-row">
                                    <div class="span"><span>翻译</span></div>
                                    <div class="text">
                                        <textarea name="trans-text" v-model="item.trans" rows="3"></textarea>
                                    </div>
                                </li>
                            </ul>


                        </div>
                    </div>
                </template>
                <template v-else>
                    <el-empty class="container__audio-empty"
                        description="请在左边图片区域按住鼠标左键画出点读区域，为保证点读效果，请标注音频对应的所有点读区域。"></el-empty>
                </template>
            </el-col>
        </el-row>
        <audio v-if="this.audioList.length" ref="tryAudio" :src="this.audioList[0].url"></audio>
        <span slot="footer" class="dialog-footer">
            <el-button @click="handleClose">取 消</el-button>
            <el-button type="primary" @click="handleConfirm">确 定</el-button>
        </span>
    </el-dialog>
</template>
<script>

export default {
    name: 'MakePoint',
    props: {
        dialogVisible: {
            type: Boolean,
            default: false
        },
        currentItem: {
            type: Object,

        },
        audioList: {
            type: Array,
            default: () => {
                return []
            }
        },
        currentIndex: {
            type: Number,
            default: -1
        },
        currentTurnPoint: {
            type: Number,
            default: 0
        },
        prevTurnPoint: {
            type: Number,
            default: 0
        }
    },
    data() {
        return {
            currentRepaint: -1,
            currentPlay: -1,
            isDrawing: false,
            startLocation: { x: 0, y: 0 },
            lineStyle: 'black',
            isDrawing: false,
            tryAudioInterval: null,
            item: {},
        }
    },
    computed: {

        myCanvas() {
            return this.$refs.myCanvas
        },
        context() {
            return this.myCanvas.getContext('2d')
        },
        tryAudio() {
            return this.$refs.tryAudio
        }

    },
    mounted() {
        if (this.item.pointList.length > 0) {
            setTimeout(() => {
                // 根据比例获取绘制图像的宽高
                this.item.pointList = this.item.pointList.map(item => {
                    const { width, height } = this.myCanvas
                    let start = {}
                    let end = {}
                    start.x = item.px * width
                    start.y = item.py * height
                    end.x = (item.px + item.pw) * width
                    end.y = (item.py + item.ph) * height
                    item.start = start
                    item.end = end;
                    return item
                })
                this.context.clearRect(0, 0, this.myCanvas.width, this.myCanvas.height)
                this.repaintHistory()
            }, 600)
        }

    },
    watch: {
        currentItem: {
            handler(newVal) {
                if (newVal) {
                    this.item = { ...newVal }
                }
            },
            immediate: true
        }
    },

    methods: {
        handlePlay(obj, item, type) {
            if (type == 'start' && item.startTime) {
                obj.target.currentTime = item.startTime
            }
            if (type == 'end' && item.endTime) {
                obj.target.currentTime = item.endTime
            }
        },
        delPointer(index) {
            this.$confirm('此操作将删除该点读区域, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                this.item.pointList.splice(index, 1)
                this.context.clearRect(0, 0, this.myCanvas.width, this.myCanvas.height)
                this.repaintHistory()
            })
        },

        handleConfirm() {
            const checkRes = this.checkBeforeSubmit();
            if (!checkRes) {
                return false;
            }
            this.$emit('confirm', this.item, this.currentIndex)
        },
        checkBeforeSubmit() {
            let { pointList } = this.item
            if (pointList.length == 0) {
                this.item.hasEdit = false;
                // this.$message.error('请在左边图片区域按住鼠标左键画出点读区域')
                return true;
            }
            for (let i = 0; i < pointList.length; i++) {
                if (this.currentIndex == 0 && i == 0 && pointList[i].endTime <= 0) {

                    this.$message.error(`请设置第${i + 1}个点读区域的结束时间`)
                    return false
                }
                if (this.currentIndex == 0 && i > 0 && (Number(this.item.pointList[i].startTime) <= 0 || Number(this.item.pointList[i].endTime) <= 0)) {
                    // 校验一组数据中开始时间和结束时间是否为空
                    this.$message.error(`请设置第${i + 1}个点读区域的开始时间和结束时间`)
                    return false
                }
                if (this.currentIndex && (pointList[i].startTime <= 0 || pointList[i].endTime <= 0)) {

                    // 校验一组数据中开始时间和结束时间是否为空
                    this.$message.error(`请设置第${i + 1}个点读区域的开始时间和结束时间`)
                    return false
                }

                // 判断每个的结束时间不能小于开始时间
                if (Number(this.item.pointList[i].endTime) <= Number(this.item.pointList[i].startTime)) {
                    this.$message.error(`第${i + 1}个点读区域的结束时间不能小于开始时间`)
                    return false;
                }

                if (i > 0) {
                    if (Number(pointList[i].startTime) < Number(pointList[i - 1].endTime)) {
                        this.$message.error(`第${i + 1}个点读区域的开始时间不能小于第${i}的结束时间`)
                        return false;
                    }
                }

                if (!pointList[i].text.trim()) {
                    this.$message.error(`第${i + 1}个点读区域的原文内容不能为空`)
                    return false
                }
                // 检查内容只能是英文和 英文标点符号 使用正则
                // 我想判斷 一個字符串 的内容 必須是英文和 英文标点符号 的内容 幫我寫一個正則
                if (!/^[a-zA-Z\s.,!?;:'"-]+$/.test(pointList[i].text)) {
                    this.$message.error(`第${i + 1}个点读区域的原文内容只能是英文和 英文标点符号`)
                    return false
                }

            }
            pointList = pointList.map((item, index) => {
                item.start = {}
                item.end = {}
                return item
            })
            this.item.hasEdit = true;
            this.item.pointList = [...pointList]
            return true
        },
        handleClose() {
            this.currentRepaint = -1
            this.$emit('update:dialogVisible', false)
            this.$emit('closeModal')
        },
        repaint(index) {
            if (index == this.currentRepaint && this.currentRepaint != -1) {
                this.currentRepaint = -1
                this.item.pointList[index].repaint = false
                this.context.clearRect(0, 0, this.myCanvas.width, this.myCanvas.height)
                this.repaintHistory()
            } else {
                if (this.currentRepaint != -1) {
                    this.$message.error(
                        `当前正在重画第${this.currentRepaint}个点读区域，请画完或者点击取消再继续重画`
                    )
                    return
                }
                for (var i = 0; i < this.item.pointList.length; i++) {
                    this.item.pointList[i].repaint = false
                }

                this.currentRepaint = index
                this.item.pointList[index].repaint = true
                this.context.clearRect(0, 0, this.myCanvas.width, this.myCanvas.height)
                this.repaintHistory()
            }
        },
        handleTime(e, index, type) {
            if (type === 'start') {
                this.item.pointList[index].startTime = e.target.currentTime
            } else {
                this.item.pointList[index].endTime = e.target.currentTime
            }
        },
        setCanvasWidthHight(e) {
            const { width, height } = e.target
            if (this.myCanvas.width != width || this.myCanvas.height != height) {
                this.myCanvas.width = width
                this.myCanvas.height = height
            }
        },

        getLocation(x, y) {
            const rect = this.myCanvas.getBoundingClientRect()
            return {
                x: x - rect.left,
                y: y - rect.top,
            }
        },

        handleMouseDown(e) {
            this.isDrawing = true
            const location = this.getLocation(e.clientX, e.clientY)
            this.startLocation = { ...location }
        },
        handleMouseOut(e) {
            this.isDrawing = false
        },

        handleMouseMove(e) {
            if (this.isDrawing) {
                const endLocation = this.getLocation(e.clientX, e.clientY)
                this.context.clearRect(0, 0, this.myCanvas.width, this.myCanvas.height)
                this.repaintHistory()
                this.drawHorizontalLine(this.startLocation, endLocation)
                this.drawVerticalLine(this.startLocation, endLocation)
            }
        },


        repaintHistory() {
            const { pointList } = this.item;
            if (pointList.length == 0) return
            let idx = 0
            for (let i = 0; i < pointList.length; i++) {
                idx++
                if (pointList[i].repaint) continue
                this.drawHorizontalLine(pointList[i].start, pointList[i].end)
                this.drawVerticalLine(pointList[i].start, pointList[i].end)
                this.context.fillStyle = '#247ac5'
                this.context.fillRect(pointList[i].start.x, pointList[i].start.y, 20, 20)
                this.context.fillStyle = '#fff'
                this.context.font = '15px Georgia'
                this.context.fillText(idx, pointList[i].start.x + 6, pointList[i].start.y + 12)
            }
        },
        getRepaintIndexIndex() {
            for (var i = 0; i < this.item.pointList.length; i++) {
                if (this.item.pointList[i].repaint) {
                    return i
                }
            }
        },

        handleMouseUp(e) {
            this.isDrawing = false
            if (this.startLocation.x < 0 || this.startLocation.y < 0) return
            const endLocation = this.getLocation(e.clientX, e.clientY)
            if (this.startLocation.x == endLocation.x && this.startLocation.y == endLocation.y)
                return
            if (endLocation.x < this.startLocation.x) {
                const tx = this.startLocation.x
                this.startLocation.x = endLocation.x
                endLocation.x = tx
            }
            if (endLocation.y < this.startLocation.y) {
                const ty = this.startLocation.y
                this.startLocation.y = endLocation.y
                endLocation.y = ty
            }
            if (
                Math.abs(endLocation.x - this.startLocation.x) > 5 &&
                Math.abs(endLocation.y - this.startLocation.y) > 5
            ) {
                this.handleMouseUpPoint(endLocation)
            }

            //清除上一次的位置
            this.startLocation.x = -1
            this.startLocation.y = -1
        },

        handleMouseUpPoint(endLocation) {
            const isRepoint = this.currentRepaint !== -1

            this.drawHorizontalLine(this.startLocation, endLocation)
            this.drawVerticalLine(this.startLocation, endLocation)
            const start = { ...this.startLocation }
            const end = { ...endLocation }
            const px = Math.round((this.startLocation.x / this.myCanvas.width) * 10000) / 10000
            const py = Math.round((this.startLocation.y / this.myCanvas.height) * 10000) / 10000
            const pw = Math.round(((end.x - start.x) / this.myCanvas.width) * 10000) / 10000
            const ph = Math.round(((end.y - start.y) / this.myCanvas.height) * 10000) / 10000

            // 获取该点的 更新时间, 取当前时间戳
            const data = {
                px,
                py,
                pw,
                ph,
                startTime: 0,
                endTime: 0,
                text: '',
                trans: '',
                start,
                end,
                repaint: false,
            }
            if (isRepoint) {
                const index = this.getRepaintIndexIndex()
                this.item.pointList.splice(index, 1, { ...data })
                this.context.fillStyle = '#247ac5'
                this.context.fillRect(this.startLocation.x, this.startLocation.y, 20, 20)
                this.context.fillStyle = '#fff'
                this.context.font = '15px Georgia'
                this.context.fillText(index + 1, this.startLocation.x + 6, this.startLocation.y + 12)
                this.currentRepaint = -1
            } else {
                const lastIndex = this.getLastIndex()
                // 如果前一个点读有结束时间 新建的数据点以前一个的结束时间

                if (lastIndex - 2 >= 0) {
                    const preItem = this.getPreItem()
                    if (preItem) {
                        data.startTime = preItem.endTime
                        data.endTime = preItem.endTime
                    }

                }
                // 创建 div
                this.context.fillStyle = '#247ac5'
                this.context.fillRect(this.startLocation.x, this.startLocation.y, 20, 20)
                this.context.fillStyle = '#fff'
                this.context.font = '15px Georgia'
                this.context.fillText(lastIndex, this.startLocation.x + 6, this.startLocation.y + 12)
                if (this.item.pointList.length == 0) {
                    data.startTime = this.prevTurnPoint
                    data.endTime = this.currentTurnPoint
                }

                this.item.pointList.push(data)
            }
        },
        drawHorizontalLine(start, end) {
            this.context.strokeStyle = this.lineStyle
            this.context.beginPath()
            this.context.moveTo(start.x, start.y)
            this.context.lineTo(end.x, start.y)
            this.context.stroke()
            this.context.closePath()

            this.context.beginPath()
            this.context.moveTo(start.x, end.y)
            this.context.lineTo(end.x, end.y)
            this.context.stroke()
            this.context.closePath()
        },
        drawVerticalLine(start, end) {
            this.context.strokeStyle = this.lineStyle
            this.context.beginPath()
            this.context.moveTo(start.x, start.y)
            this.context.lineTo(start.x, end.y)
            this.context.stroke()
            this.context.closePath()

            this.context.beginPath()
            this.context.moveTo(end.x, start.y)
            this.context.lineTo(end.x, end.y)
            this.context.stroke()
            this.context.closePath()
        },
        getLastIndex() {
            let index = 1
            for (let i = 0; i < this.item.pointList.length; i++) {
                index++
            }
            return index
        },
        getPreItem() {
            return this.item.pointList[this.item.pointList.length - 1]
        },
        changeBorderColor() {
            this.lineStyle = this.lineStyle === 'black' ? 'white' : 'black'
            this.context.clearRect(0, 0, this.myCanvas.width, this.myCanvas.height)
            this.repaintHistory()
        }
        ,
        tryListen(index) {
            let currentItem = this.item.pointList[index]

            if (!currentItem) {
                this.$message.error('请先画点读区域')
                return false;
            }
            if (this.currentIndex == 0 && index == 0) {
                if (Number(this.item.pointList[index].endTime) <= 0) {
                    this.$message.error('请先设置结束时间')
                    return false;
                }
            } else {
                if (Number(this.item.pointList[index].startTime) <= 0) {
                    this.$message.error('请先设置开始时间')
                    return false;
                }
                if (Number(this.item.pointList[index].endTime) <= 0) {
                    this.$message.error('请先设置结束时间')
                    return false;
                }
            }
            if (this.currentPlay !== index && this.currentPlay !== -1) {
                this.$message.error(`请先关闭${this.currentPlay + 1}试听`)
                return false;
            }
            if (Number(this.item.pointList[index].endTime) <= Number(this.item.pointList[index].startTime)) {
                this.$message.error('音频结束时间要大于开始时间。')
                return
            }
            this.currentPlay = index
            if (currentItem.isPlaying) {
                this.tryAudio.pause()
                // 奖变更的数据替换原来的数据, 达到响应式
                this.item.pointList.splice(index, 1, { ...currentItem, isPlaying: false })
                clearInterval(this.tryAudioInterval)
                return
            }
            this.tryAudio.currentTime = currentItem.startTime || 0
            this.item.pointList[index].isPlaying = true
            this.item.pointList.splice(index, 1, { ...currentItem, isPlaying: true })
            this.tryAudio.play()

            this.tryAudioInterval = setInterval(() => {
                let c = this.tryAudio.currentTime
                if (c >= currentItem.endTime) {
                    this.tryAudio.pause()
                    clearInterval(this.tryAudioInterval)
                    this.currentPlay = -1
                    this.item.pointList.splice(index, 1, { ...currentItem, isPlaying: false })
                }
            }, 50)
        },
        translatePointer() {
            this.$message.warning('暂时不支持!,请手动填写内容')
        }
    },
    beforeDestroy() {
        clearInterval(this.tryAudioInterval)
    }

}





</script>
<style lang="scss" scoped>
.container {
    width: 100%;
    min-width: 1280px;
    padding: 0 10px;
    height: 100%;

    ::v-deep .el-form-item {
        margin-bottom: 22px;
    }

    &__pointer {
        position: relative;
        overflow: hidden;
        padding: 0 20px;

        &-title {
            position: relative;
            height: 50px;
            line-height: 50px;
            background-color: #fff;
            color: #000;
            display: flex;
            justify-content: space-between;
            align-items: center;

            &-btn {
                position: absolute;
                right: 10px;
                top: 3px;
            }
        }

        &-image {
            position: relative;
            border: #ccc 1px solid;
            background-color: #f0ffff;
            width: 100%;
            height: 100%;

            canvas {
                position: absolute;
                cursor: pointer;
            }

            img {
                width: 100%;
            }
        }
    }

    &__audio {
        padding: 5px 10px;

        &-row {
            border: #000 1px solid;
            padding: 5px 10px;
            margin-bottom: 10px;

            &-top {
                display: flex;
                justify-content: space-between;
                align-items: center;

                h1 {
                    font-size: 18px;
                }
            }

            &-content {
                border: #ccc 1px solid;
                background-color: #f0ffff;
                margin-top: 10px;
                padding: 10px 20px;

                h2 {
                    font-size: 15px;
                }

                b {
                    font-size: 15px;
                    margin-left: 5px;
                }


                ul {
                    width: 100%;

                    li {
                        display: flex;
                        align-items: center;
                        justify-content: flex-start;
                        margin-bottom: 10px;
                        margin-right: 0;

                        input {
                            // margin-left: 10px;
                            margin-right: 10px;
                        }

                        audio {
                            width: 60%;
                        }
                    }
                }

                &-time {
                    display: flex;
                    align-items: center;

                    &-ul {
                        margin: 0;
                        padding: 0;

                        span {
                            width: 200px;
                        }
                    }

                    .el-button {
                        margin-left: 30px;
                    }
                }

                &-text {
                    margin: 0;
                    padding: 0;

                    &-row {
                        width: 100%;

                        .span {
                            width: 70px;
                        }

                        .text {
                            // 我想这个元素占满剩余空间
                            overflow: hidden;
                            flex-grow: 1;

                            textarea {
                                width: 80%;
                            }
                        }
                    }
                }

            }
        }

    }
}
</style>